package com.hzsai.streamapi;

import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Stream;

/**
 * hzsai 2020/2/12
 * usage:
 * Stream是lazy的
 * filter(Predicate)表示对流里面的元素的推测、估算，返回True,False值（当然这个估计函数是你写啦）
 **/
public class IteratorToStream {


     public static class Main {
         private Integer count = 0;

        private String content;

        private List<String> words;

        private static final String letter = "letter.txt";

        public void go() throws IOException {
            content = new String(Files.readAllBytes(Paths.get(letter)), StandardCharsets.UTF_8);
            words = Arrays.asList(content.split("[\\P{L}]+"));
            for (String word : words) {
                System.out.println(word);
                if (word.length() > 5) count += 1;
            }
            System.out.println(count);

            // filter().count()
            long cnt2 = words.stream().filter(w -> w.length() > 5).count();
            long cnt3 = words.stream().filter(w -> w.length() > 5).filter(w -> w.length() > 7).mapToLong(w -> 1L).sum();
            System.out.println(cnt2);
            System.out.println(cnt3);

            long cnt4 = words.parallelStream().filter(w -> w.length() > 5).count();
            System.out.println(cnt4);

            Stream<String> wordss = Stream.of(content.split("[\\P{L}]+"));
            wordss.filter(w -> w != null).count();

            // 无限生成
            Stream<Double> randd = Stream.generate(/*() -> Math.random()*/Math::random);
            //randd.forEach(System.out::println);
            Stream<String> echos = Stream.generate(() -> "a word.");
            //echos.forEach(System.out::println);

            Stream<BigInteger> bigIter = Stream.iterate(BigInteger.valueOf(1), n -> n.multiply(BigInteger.valueOf(2)));
            //bigIter.forEach(System.out::println);

            // 有许多的类新增了变成stream的方法
            Stream<String> pt = Pattern.compile("[\\P{L}]+").splitAsStream(content);

            words.forEach(System.out::println);
            // 流，意味着只能被消费一次
            //wordss.map(String::toUpperCase);
            //wordss.forEach(System.out::println);
            Stream<String> upperWords = words.stream().map(String::toUpperCase);
            upperWords.forEach(System.out::println);
            //words.forEach(System.out::println);

            Stream<Character> InitalWord = words.stream().map(w -> w.charAt(0)).map(w -> Character.toUpperCase(w)).sorted().distinct();

            InitalWord.forEach(System.out::println);
            System.out.println();

            Stream<Character> helloStr = listToStream("Hello");
            helloStr.forEach(System.out::println);

            Stream<Stream<Character>> result = words.stream().map(w -> listToStream(w));
            //result.forEach(System.out::print); // 输出的是stream对象
            result.forEach(w -> w.forEach(System.out::print)); // 逐个输出
            System.out.println();
            // [ [], [], [], [], [] ] -> flatMap  [ , , , , , , , ... ]
            Stream<Character> result2 = words.stream().flatMap(w -> listToStream(w));
            result2.forEach(System.out::print);

            // f:T -> G(U), g: U -> G(U)
            Stream<Double> upToOneHundurd = Stream.generate(Math::random).limit(100);
            upToOneHundurd.forEach(System.out::print);
            System.out.println();

            Stream<BigInteger> oneHundurd = Stream.iterate(BigInteger.ONE, n -> n.add(BigInteger.ONE)).limit(100);
            oneHundurd.forEach(System.out::print);

            Stream<Character> combined = Stream.concat(Stream.generate(() -> 'a'), listToStream("bbb"));
            //combined.forEach(System.out::println);

            Stream<String> newStringStream = Arrays.stream(content.split("[\\P{L}]+")).skip(1);
            newStringStream.forEach(System.out::println);

            Stream<String> newStringStream1 = Arrays.stream(content.split("[\\P{L}]+")).skip(1);
            newStringStream1.forEach(w -> System.out.println(capitalize(w)));

            Object[] powers = Stream.iterate(1.0, p -> p * 2.0).peek(System.out::println).limit(20).toArray();

            Stream<String> uniqueWord = Stream.of("aaa", "aaa", "bbb", "ccc", "aaa").distinct();
            uniqueWord.forEach(System.out::println);

            Stream<String> sortedWord = words.stream().sorted(Comparator.comparing(String::length).reversed());
            sortedWord.forEach(System.out::println);
        }
    }


    public static void main(String[] args) throws IOException {
        Main instance = new Main();
        instance.go();
    }

    public static Stream<Character> listToStream(String s) {
         List<Character> result = new ArrayList<>();

         for (Character c : s.toCharArray()) result.add(c);
         return result.stream();
    }

    public static String capitalize(String s) {
         StringBuilder sb = new StringBuilder();
         sb.append(Character.toUpperCase(s.charAt(0)));
         for (int i = 1; i < s.length(); ++i) {
             sb.append(s.charAt(i));
         }

         return sb.toString();
    }
}
